package com.oystertech.sportcms.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oystertech.sportcms.common.constant.SecurityConstants;
import com.oystertech.sportcms.common.constant.SystemConstants;
import com.oystertech.sportcms.common.util.SecurityUtils;
import com.oystertech.sportcms.converter.TeamConverter;
import com.oystertech.sportcms.converter.UserConverter;
import com.oystertech.sportcms.mapper.SysUserMapper;
import com.oystertech.sportcms.model.bo.UserBO;
import com.oystertech.sportcms.model.bo.UserFormBO;
import com.oystertech.sportcms.model.dto.UserAuthInfo;
import com.oystertech.sportcms.model.entity.SysUser;
import com.oystertech.sportcms.model.entity.SysUserTeam;
import com.oystertech.sportcms.model.entity.Team;
import com.oystertech.sportcms.model.form.UserForm;
import com.oystertech.sportcms.model.query.UserPageQuery;
import com.oystertech.sportcms.model.vo.TeamVO;
import com.oystertech.sportcms.model.vo.UserExportVO;
import com.oystertech.sportcms.model.vo.UserInfoVO;
import com.oystertech.sportcms.model.vo.UserPageVO;
import com.oystertech.sportcms.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户业务实现类
 *
 * @author haoxr
 * @since 2022/1/14
 */
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

	private final PasswordEncoder passwordEncoder;

	private final SysUserRoleService userRoleService;

	private final SysUserTeamService userTeamService;

	private final UserConverter userConverter;

	private final TeamConverter teamConverter;

	private final SysMenuService menuService;

	private final TeamService teamService;

	private final RedisTemplate redisTemplate;

	/**
	 * 获取用户分页列表
	 *
	 * @param queryParams
	 * @return
	 */
	@Override
	public IPage<UserPageVO> getUserPage(UserPageQuery queryParams) {

		// 参数构建
		int pageNum = queryParams.getPageNum();
		int pageSize = queryParams.getPageSize();
		Page<UserBO> page = new Page<>(pageNum, pageSize);

		// 查询数据
		Page<UserBO> userBoPage = this.baseMapper.getUserPage(page, queryParams);

		// 实体转换
		Page<UserPageVO> userVoPage = userConverter.bo2Vo(userBoPage);

		return userVoPage;
	}

	/**
	 * 获取用户详情
	 *
	 * @param userId
	 * @return
	 */
	@Override
	public UserForm getUserFormData(Long userId) {
		UserFormBO userFormBO = this.baseMapper.getUserDetail(userId);
		// 实体转换po->form
		UserForm userForm = userConverter.bo2Form(userFormBO);
		return userForm;
	}

	/**
	 * 新增用户
	 *
	 * @param userForm 用户表单对象
	 * @return
	 */
	@Transactional
	@Override
	public boolean saveUser(UserForm userForm) {

		String username = userForm.getUsername();

		long count = this.count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
		Assert.isTrue(count == 0, "用户名已存在");

		// 实体转换 form->entity
		SysUser entity = userConverter.form2Entity(userForm);

		// 设置默认加密密码
		String defaultEncryptPwd = passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD);
		entity.setPassword(defaultEncryptPwd);

		// 新增用户
		boolean result = this.save(entity);

		if (result) {
			// 保存用户角色
			userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
		}
		return result;
	}

	/**
	 * 更新用户
	 *
	 * @param userId   用户ID
	 * @param userForm 用户表单对象
	 * @return
	 */
	@Override
	@Transactional
	public boolean updateUser(Long userId, UserForm userForm) {

		String username = userForm.getUsername();

		long count = this.count(new LambdaQueryWrapper<SysUser>()
				.eq(SysUser::getUsername, username)
				.ne(SysUser::getId, userId)
		);
		Assert.isTrue(count == 0, "用户名已存在");

		// form -> entity
		SysUser entity = userConverter.form2Entity(userForm);

		// 修改用户
		boolean result = this.updateById(entity);

		if (result) {
			// 保存用户角色
			userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
		}
		return result;
	}

	/**
	 * 删除用户
	 *
	 * @param idsStr 用户ID，多个以英文逗号(,)分割
	 * @return
	 */
	@Override
	public boolean deleteUsers(String idsStr) {
		Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的用户数据为空");
		// 逻辑删除
		List<Long> ids = Arrays.stream(idsStr.split(","))
				.map(Long::parseLong).collect(Collectors.toList());
		return this.removeByIds(ids);
	}

	/**
	 * 修改用户密码
	 *
	 * @param userId   用户ID
	 * @param password 用户密码
	 * @return true|false
	 */
	@Override
	public boolean updatePassword(Long userId, String password) {
		return this.update(new LambdaUpdateWrapper<SysUser>()
				.eq(SysUser::getId, userId)
				.set(SysUser::getPassword, passwordEncoder.encode(password))
		);
	}

	/**
	 * 根据用户名获取认证信息
	 *
	 * @param username 用户名
	 * @return 用户认证信息 {@link UserAuthInfo}
	 */
	@Override
	public UserAuthInfo getUserAuthInfo(String username) {
		UserAuthInfo userAuthInfo = this.baseMapper.getUserAuthInfo(username);
		if (userAuthInfo != null) {
			Set<String> roles = userAuthInfo.getRoles();
			if (CollectionUtil.isNotEmpty(roles)) {
				Set<String> perms = menuService.listRolePerms(roles);
				userAuthInfo.setPerms(perms);
			}
		}
		return userAuthInfo;
	}


	/**
	 * 获取导出用户列表
	 *
	 * @param queryParams
	 * @return
	 */
	@Override
	public List<UserExportVO> listExportUsers(UserPageQuery queryParams) {
		return this.baseMapper.listExportUsers(queryParams);
	}

	/**
	 * 获取登录用户信息
	 *
	 * @return
	 */
	@Override
	public UserInfoVO getUserLoginInfo() {
		// 登录用户entity
		SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>()
				.eq(SysUser::getUsername, Objects.requireNonNull(SecurityUtils.getUser()).getUsername())
				.select(
						SysUser::getId,
						SysUser::getNickname,
						SysUser::getAvatar
				)
		);
		// entity->VO
		UserInfoVO userInfoVO = userConverter.entity2UserInfoVo(user);

		// 用户角色集合
		Set<String> roles = SecurityUtils.getRoles();
		userInfoVO.setRoles(roles);

		// 用户权限集合
		Set<String> perms = (Set<String>) redisTemplate.opsForValue().get(SecurityConstants.USER_PERMS_CACHE_PREFIX + user.getId());
		userInfoVO.setPerms(perms);

		// 所属队伍ID集合
		List<Long> teamIds = (List<Long>) userTeamService.listTeamIdsByUserId(user.getId());
		userInfoVO.setTeamIds(teamIds);

		// 所属队伍集合
		List<Team> teams = teamService.lambdaQuery().in(Team::getId, teamIds).list();
		List<TeamVO> teamVOs = new ArrayList<>();
		for (Team team : teams) teamVOs.add(teamConverter.entity2TeamVo(team));
		userInfoVO.setTeams(teamVOs);

		return userInfoVO;
	}
}
